#include "uhm/common.hxx"
#include "uhm/util.hxx"

#include "uhm/discrete/base/tree.hxx"
#include "uhm/discrete/base/ops.hxx"

using namespace uhm;

#define N 3

typedef Int_          Data;
typedef Tree_<Data,N> Tree;

static Int_ data_show(Tree::Tnd_* tnd);

Int_ data_show(Tree::Tnd_* tnd) {
  std::cout << tnd->get_data() << std::endl;
  return true;
}

Int_ main (int argc, char **argv) {

  Tree tree;
  Tree::Tnd_ *n, *c;
  tree.set_size(10);
  tree.reserve();

  n = tree.add_node(0);
  tree.set_root(n);

  c = tree.add_node(1); n->add_child(c); c->set_parent(n);

  c = tree.add_node(2); n->add_child(c); c->set_parent(n);
  c = tree.add_node(3); n->add_child(c); c->set_parent(n);
    
  n = n->get_child(1);
  c = tree.add_node(4); n->add_child(c); c->set_parent(n);
  c = tree.add_node(5); n->add_child(c); c->set_parent(n);

  n = n->get_child(0);
  c = tree.add_node(6); n->add_child(c); c->set_parent(n);
  c = tree.add_node(7); n->add_child(c); c->set_parent(n);

  tree.set_gen();

  std::cout << tree << std::endl;

  std::cout << "op_leaf_to_me_seq\n";
  op_leaf_to_me_seq<Tree>(tree.get_root(), &data_show);

  std::cout << "op_me_to_leaf_seq\n";
  op_me_to_leaf_seq<Tree>(tree.get_root(), &data_show);

  std::cout << "op_leaf_to_me_par\n";
#pragma omp parallel
  {
#pragma omp single nowait
    op_leaf_to_me_par<Tree>(tree.get_root(), &data_show);
  }
  std::cout << "op_me_to_leaf_par\n";
#pragma omp parallel
  {
#pragma omp single nowait
    op_me_to_leaf_par<Tree>(tree.get_root(), &data_show);
  }

  return true;
}


